#include "string.h"
#include "rtthread.h"
#include "usr_data_buf.h"
#include "global_define.h"

#define UART_DTU_DEVICE "uart4"

#define PKGT_OUTTIME_MIN_MS 20//两包数据的最小分割时间，单位:ms
#define PKGT_OUTTIME_DEFAULT_MS 20
#define PKGT_OUTTIME_MAX_MS 10000

#define uart_pkgt_buf_size 50 //长些方便以后添加指令解析
typedef struct
{
 rt_thread_t thread;
 rt_device_t device;
 rt_sem_t recv_sem;
 uint16_t recv_outtime_ms;//串口超时时间，默认20ms
 
 char buf[uart_pkgt_buf_size+1]; //提取数据的缓存
 
}UART_DTU_CTR_STR;

UART_DTU_CTR_STR* p_uart_dtu_ctr=RT_NULL;

void uart_dtu_entry(void * parameter)
{
	rt_err_t  err;
	rt_size_t read_len;
	uint32_t recv_flag=0;
	while(1)
	{
		err=rt_sem_take(p_uart_dtu_ctr->recv_sem,MS_TO_TICK(p_uart_dtu_ctr->recv_outtime_ms));
		if(err==RT_EOK)
		{
			while(1)
			{
				read_len=rt_device_read(p_uart_dtu_ctr->device, 0,p_uart_dtu_ctr->buf,uart_pkgt_buf_size);
				if(read_len)
				{
					recv_flag=1;
					//向用户缓存存储数据
					write_usr_buf(p_uart_dtu_ctr->buf, read_len,0,DATA_SOURCE_DTU_UART,0, 1);
				}
				else
				{
					break;
				}
			}
			
		}
		else//信号量超时
		{
			if(recv_flag)//数据存储结束
			{
				write_usr_buf(p_uart_dtu_ctr->buf, 0,1,DATA_SOURCE_DTU_UART,0, 1);//无数据，
				recv_flag=0;
			}
		}
	}
	
}



rt_err_t uart_dtu_rx_callback(rt_device_t dev, rt_size_t size)
{
	rt_sem_release(p_uart_dtu_ctr->recv_sem);
	return RT_EOK;
}


int uart_dtu_init(void)
{
	int outtime=PKGT_OUTTIME_DEFAULT_MS;
	char* p_para=RT_NULL;
	struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
	config.baud_rate = BAUD_RATE_9600;
	
	if(p_uart_dtu_ctr==RT_NULL)
	{
		p_uart_dtu_ctr=rt_malloc(sizeof(UART_DTU_CTR_STR));
		RT_ASSERT(p_uart_dtu_ctr);
		memset(p_uart_dtu_ctr,0,sizeof(UART_DTU_CTR_STR));
	}
	

	/*查找设备*/
	if(p_uart_dtu_ctr->device==RT_NULL)
	{
		p_uart_dtu_ctr->device=rt_device_find(UART_DTU_DEVICE);
		RT_ASSERT(p_uart_dtu_ctr->device);
	}

	/*串口参数的获取和检查*/
	
	p_para=ef_get_env("DTU_UART");
 	if(p_para)//有参数配置;无参数配置使用默认值
 	{
 		uint32_t baud_rate,data_bit,stop_bit;
 		char parity;
 		rt_kprintf("dtu_uart_cfg:%s;",p_para);
 		if(5==sscanf(p_para,"%u,%u,%c,%u:%u",&baud_rate,&data_bit,&parity,&stop_bit,&outtime))
 		{
 			if((baud_rate<300)||(baud_rate>3000000))
 			{
 				rt_kprintf("baud_rate range err:%u",baud_rate);
 				baud_rate=9600;
 			}
 			config.baud_rate=baud_rate;
 			
 			if((data_bit<DATA_BITS_5)||(data_bit>DATA_BITS_8))
 			{
 				rt_kprintf("data_bit range err:%u",data_bit);
 				data_bit=DATA_BITS_8;
 			}
 			config.data_bits=data_bit;
 			
 			switch(parity)
 			{
 				case 'N':
 						config.parity=PARITY_NONE;
 						break;
 				case 'E':
 						config.parity=PARITY_EVEN;
 						break;
 				case 'O':
 						config.parity=PARITY_ODD;
 						break;
 				default:
 					rt_kprintf("parity range('N/O/E') err:%c",parity);
 					config.parity=PARITY_NONE;
 					break;
 			}
 			
			switch(stop_bit)
			{
				case 1:
						config.stop_bits=STOP_BITS_1;
						break;
				case 2:
						config.stop_bits=STOP_BITS_2;
						break;
				case 3:
						config.stop_bits=STOP_BITS_3;
						break;
				default:
					rt_kprintf("stop_bits range(1/2/3) err:%u",stop_bit);
					config.stop_bits=STOP_BITS_1;
					break;
			}
			
			if((outtime<PKGT_OUTTIME_MIN_MS)||(outtime>PKGT_OUTTIME_MAX_MS))
			{
				outtime=PKGT_OUTTIME_DEFAULT_MS;
			}
 		}
 		
 	}

 	p_uart_dtu_ctr->recv_outtime_ms=outtime;
 	
 	if(p_uart_dtu_ctr->recv_sem==RT_NULL)
	{
		p_uart_dtu_ctr->recv_sem=rt_sem_create("uart_dtu", 0, RT_IPC_FLAG_FIFO);
		RT_ASSERT(p_uart_dtu_ctr->recv_sem);
	}
  rt_device_control(p_uart_dtu_ctr->device, RT_DEVICE_CTRL_CONFIG, &config);
  rt_device_set_rx_indicate(p_uart_dtu_ctr->device,uart_dtu_rx_callback);
	rt_device_open(p_uart_dtu_ctr->device, RT_DEVICE_FLAG_INT_RX|RT_DEVICE_FLAG_INT_TX);
	

	if(p_uart_dtu_ctr->thread==RT_NULL)
	{
		p_uart_dtu_ctr->thread=rt_thread_create("uart_dtu", uart_dtu_entry, (void * )0, 1024,8,20);
		RT_ASSERT(p_uart_dtu_ctr->thread);
		rt_thread_startup(p_uart_dtu_ctr->thread);
	}
	


	return 1;
}


